package logic;

import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.datatransfer.DataFlavor;
import java.io.File;
import java.io.Serializable;
import java.util.List;
import javax.swing.JFileChooser;
import javax.swing.JTextArea;
import javax.swing.TransferHandler;
import qw.easyFrame.enums.SelectionMode;
import qw.easyFrame.view.util.SwingUtil;
import view.EasyTextPane;

/**
 * 文件选择器.
 * @author Rex
 *
 */
public class EasyFileChooser implements Serializable {
	private static final long serialVersionUID = 20240920L;
	
	private Font font;

	/**
	 * 文字提示区.
	 */
	private EasyTextPane area;
	
	/**
	 * 默认打开的位置.
	 */
	private File startDir;
	
	/**
	 * 选择模式.
	 */
	private SelectionMode mode;
	
	/**
	 * 首次打开文件选择器时默认打开桌面，
	 * 默认不支持多选，
	 * 打开文件选择器时默认清理文字提示区.
	 * @param area 文字提示区
	 * @param mode 选择模式
	 */
	public EasyFileChooser(EasyTextPane area, SelectionMode mode) {
		this.area = area;
		this.startDir = SwingUtil.getDesktop();
		this.mode = mode;
	}
	
	public void setFont(Font font) {
		this.font = font;
	}

	/**
	 * 打开文件选择器.
	 * @return
	 */
	public File[] choose() {
		// 清理文字提示区
		area.clear();

		// 设置提示文字
		JTextArea textArea = new JTextArea("若要选中当前\r\n所在的文件夹,\r\n直接点击\"取消\"\r\n按钮返回原窗\r\n口即可");
		textArea.setEditable(false);
		
		// 新建JFileChooser，初始化时同时设置默认路径
		JFileChooser chooser = new JFileChooser(startDir, null);
		// 支持文件（文件夹）拖拽功能
		dragFiles(chooser);
		// 添加文字提示区
		chooser.setAccessory(textArea);
		// 设置字体
		updateFont(chooser, font);

		// 默认选择当前打开的文件夹
		chooser.setSelectedFile(startDir);
		// 设置选择模式
		chooser.setFileSelectionMode(mode.getMode());
		// 设置是否支持多选
		chooser.setMultiSelectionEnabled(false);
		// 定义弹出的文件选择器框
		chooser.showDialog(area, mode.getTitle());

		return checkFiles(area, chooser.getSelectedFile());
	}

	/**
	 * 文件拖拽功能.
	 * @param chooser
	 */
	private final static void dragFiles(JFileChooser chooser) {
		chooser.setTransferHandler(new TransferHandler() {
			private static final long serialVersionUID = 20240802L;

			@Override
			public boolean canImport(TransferSupport info) {
                // 检查是否支持拖拽的数据类型
                return true;
            }
			
            @Override
			public boolean importData(TransferHandler.TransferSupport info) {
				// 处理拖拽的数据
				if (!info.isDrop())
					return false;

				// 获取拖拽的文件列表
				try {
					List<?> files = (List<?>) info.getTransferable().getTransferData(DataFlavor.javaFileListFlavor);
					for (Object file : files)
						if (file instanceof File)
							chooser.setSelectedFile((File) file);

				} catch (Exception e) {
					return false;
				}


				return true;
			}
		});
	}
	
	/**
	 * 验证文件.
	 * @param area
	 * @param files
	 */
	private final static File[] checkFiles(EasyTextPane area, File... files) {
		// 标记files参数是否为空
		boolean isVoid = true;
		
		int len;
		if (files != null && (len = files.length) != 0) {
			if (len == 1 && files[0] != null && files[0].isDirectory())
				return checkPath(area, files[0]);
			else
				for (int i = 0; i < len; i++)
					if (files[i] != null) {
						area.append(files[i].getAbsolutePath());
						isVoid = false;
					}
		}
		
		if (isVoid) {
			area.append("您未选择任何文件");
			files = null;
		}

		return files;
	}

	/**
	 * 验证路径.
	 * @param area
	 * @param dir
	 */
	private final static File[] checkPath(EasyTextPane area, File dir) {
		File[] files = null;
		String path = "您未选择任何文件夹";
		String msg = null;

		if (dir != null) {
			path = dir.getAbsolutePath();
			msg = "无法读取该目录";
			int[] sums = count(dir);
			if (sums != null) {
				msg = "此路径下有" + sums[0] + "个文件," + sums[1] + "个子文件夹";
				files = new File[] { dir };
			}
		}

		// 提示用户
		area.append(path);
		if (msg != null)
			area.append(msg);

		return files;
	}

	/**
	 * 统计文件夹内的文件数目.
	 * 不包括子文件夹内的文件。
	 * @param folder
	 * @return
	 */
	private final static int[] count(File folder) {
		int[] temp = null;

		File[] files = folder.listFiles();
		if (files != null) {
			temp = new int[2];
			for (File f : files)
				if (f.isFile())
					temp[0]++;// 文件数
				else
					temp[1]++;// 子文件夹数
		}

		return temp;
	}
	
	/**
	 * 设置字体.
	 * @param comp
	 * @param font
	 */
	private static final void updateFont(Component comp, Font font) {
		comp.setFont(font);
		if (comp instanceof Container) {
			Container c = (Container) comp;
			int n = c.getComponentCount();
			for (int i = 0; i < n; i++) {
				updateFont(c.getComponent(i), font);
			}
		}
	}
	
}